const {v4: uuidv4} = require('uuid');
const createModel = require('../mongodb/createModel')
const {includeUserByUserName} = require("../utils/user");
const md5 = require('md5');


let userNameReg = /^(?!_)(?=^.{2,20}$)(?!.*?_$)[a-zA-Z0-9_\u4e00-\u9fa5]+$/,
    passwordReg = /(?=^.{6,16}$)(?=(?:.*?\d){1})(?=.*[a-z])(?=(?:.*?[A-Z]){1})(?=(?:.*?[`·~!@#$%^&*()_+}{|:;'",<.>/?\=\[\]\-\\]){1})(?!.*\s)[0-9a-zA-Z`·~!@#$%^&*()_+}{|:;'",<.>/?\=\[\]\-\\]*$/;

const schema = {
    // 用户ID
    id: {type: String, required: true},
    // 用户角色 user普通用户 root超管用户
    role: {type: String, default: 'user', enum: ['user', 'root'], required: true},
    // 用户名 长度 3-20 位只含有汉字、数字、字母、下划线不能以下划线开头和结尾
    userName: {type: String, required: true, trim: true, match: userNameReg},
    // 密码 密码长度 6-16 位,包含至少一个特殊字符,一个数字,一个大写字母和一个小写字母
    password: {type: String, required: true},
    // 昵称
    nickName: {type: String, default: ''},
    // 头像
    avatar: {type: String, default: ''},
    // 简介
    intro: {type: String, default: '这家伙很懒,什么都没留下～～～'},
    // 性别 -1保密 0女 1男
    gender: {type: Number, default: -1},
    // 出生日期
    birthday: {type: Date, default: ''},
    // 省
    province: {type: String, default: ''},
    // 市
    city: {type: String, default: ''},
    // 区
    district: {type: String, default: ''},
    // 学校
    school: {type: String, default: ''},
    // 专业
    profession: {type: String, default: ''},
    // 评论文章
    commentArticles: {type: Array, default: []},
    // 阅读文章
    viewArticles: {type: Array, default: []},
    // 创建时间
    createTime: {type: Date, default: Date.now},
}

const model = createModel('users', schema);


/**
 * 登录
 * @param userName 用户名 必填
 * @param password 密码 必填
 * @returns {Promise<object>} 请求是否成功
 */
const handleLogin = ({userName, password}) => {
    password = md5(password);
    return new Promise((resolve, reject) => {
        model.findOne({userName, password}, {_id: 0, __v: 0, password: 0}).exec((err, docs) => {
            if (docs) {
                resolve({code: 1, data: docs, msg: '登录成功'});
            } else {
                reject({code: 0, data: null, msg: '请检查用户名或密码'});
            }
        })
    })
}

/**
 * 注册
 * @param userName 用户名 必填
 * @param password 密码 必填
 * @returns {Promise<object>} 结果
 */
const handleRegister = ({userName, password}) => {
    return new Promise(async (resolve, reject) => {
        if (!userNameReg.test(userName)) {
            return reject({code: 0, data: null, msg: '用户名长度2-20位,只含有汉字、数字、字母、下划线,不能以下划线开头和结尾'});
        }
        if (!passwordReg.test(password)) {
            return reject({code: 0, data: null, msg: '密码长度6-16位,包含至少一个特殊字符,一个数字,一个大写字母和一个小写字母'});
        }
        // 查询用户是否存在 true存在 false不存在
        let isUser = await includeUserByUserName(model, {userName});
        if (!isUser) {
            password = md5(password);
            model.create({id: uuidv4(), userName, password, nickName: userName}, (err, docs) => {
                if (!err) {
                    resolve({code: 1, data: null, msg: '注册成功'});
                } else {
                    reject({code: 0, data: null, msg: err.message});
                }
            })
        } else {
            reject({code: 0, data: null, msg: '用户已存在'})
        }
    })
}

/**
 * 新增用户
 * @param params  必填 用户名 密码(排除创建时间)
 * @returns {Promise<object>} 结果
 */
const handleAdd = (params) => {
    return new Promise(async (resolve, reject) => {
        if (params.hasOwnProperty('userName') && !userNameReg.test(params.userName)) {
            return reject({code: 0, data: null, msg: '用户名长度2-20位,只含有汉字、数字、字母、下划线,不能以下划线开头和结尾'});
        }
        if (params.hasOwnProperty('password') && !passwordReg.test(params.password)) {
            return reject({code: 0, data: null, msg: '密码长度6-16位,包含至少一个特殊字符,一个数字,一个大写字母和一个小写字母'});
        }
        params.nickName = params.nickName || params.userName;
        // 查询用户是否存在 true存在 false不存在
        let isUser = await includeUserByUserName(model, params);
        if (!isUser) {
            params.id = uuidv4();
            params.password = md5(params.password);
            delete params.createTime;
            delete params.commentArticles;
            model.create(params, (err, docs) => {
                if (!err) {
                    resolve({code: 1, data: null, msg: '新增成功'});
                } else {
                    reject({code: 0, data: null, msg: err.message});
                }
            })
        } else {
            reject({code: 0, data: null, msg: '用户已存在'})
        }
    })
}

/**
 * 删除用户
 * @param id 用户ID 必填
 * @returns {Promise<object>} 结果
 */
const handleDel = ({id}) => {
    return new Promise((resolve, reject) => {
        model.deleteOne({id}, (err, docs) => {
            if (!err) {
                resolve({code: 1, data: null, msg: '删除成功'});
            } else {
                reject({code: 0, data: null, msg: err.message});
            }
        })
    })
}


/**
 * 修改
 * @param params 修改 (排除用户ID,排除创建时间)
 * @returns {Promise<object>} 结果
 */
const handleModify = (params) => {
    return new Promise((resolve, reject) => {
        if (params.hasOwnProperty('userName') && !userNameReg.test(params.userName)) {
            return reject({code: 0, data: null, msg: '用户名长度2-20位,只含有汉字、数字、字母、下划线,不能以下划线开头和结尾'});
        }
        if (params.hasOwnProperty('password') && !passwordReg.test(params.password)) {
            return reject({code: 0, data: null, msg: '密码长度6-16位,包含至少一个特殊字符,一个数字,一个大写字母和一个小写字母'});
        }
        let {id} = params;
        delete params.id;
        delete params.createTime;
        model.findOneAndUpdate({id}, params, (err, docs) => {
            if (!err) {
                resolve({code: 1, data: null, msg: '修改成功'});
            } else {
                reject({code: 0, data: null, msg: err.message});
            }
        })
    })
}

/**
 * 查询用户
 * 示例：
 * {
 *     page: 1,
 *     size: 10,
 *     userName: '',
 *     nickName: '',
 *     gender: 0,
 *     province: '',
 *     city: '',
 *     district: '',
 *     school: '',
 *     profession: '',
 *     birthdayStart: '1997-02-11',
 *     birthdayEnd: '2020-10-30'
 *     createTimeStart: '1997-02-11',
 *     createTimeEnd: '2020-10-30'
 * }
 * @param params 查询条件 (页码,数据量,用户名,昵称,性别,省,市,区,学校,专业,生日,创建时间)
 * @returns {Promise<object>} 结果
 */
const handleList = (params) => {
    const page = Number(params.page);
    const size = Number(params.size);
    const filter = {
        $match: {
            $and: [
                {userName: {$regex: params.userName || '', $options: 'i'}},
                {nickName: {$regex: params.nickName || '', $options: 'i'}},
                typeof (params.gender) === 'number' ? {gender: params.gender} : {},
                {province: {$regex: params.province || '', $options: 'i'}},
                {city: {$regex: params.city || '', $options: 'i'}},
                {district: {$regex: params.district || '', $options: 'i'}},
                {school: {$regex: params.school || '', $options: 'i'}},
                {profession: {$regex: params.profession || '', $options: 'i'}},
                params.birthdayStart ? {birthday: { $gte: new Date(params.birthdayStart + ' 00:00:00')} } : {},
                params.birthdayEnd ? {birthday: { $lte: new Date(params.birthdayEnd + ' 23:59:59')} } : {},
                params.createTimeStart ? {createTime: { $gte: new Date(params.createTimeStart + ' 00:00:00')} } : {},
                params.createTimeEnd ? {createTime: { $lte: new Date(params.createTimeEnd + ' 23:59:59')} } : {},
            ]
        }
    };
    const aggregate = [{
        $facet: {
            total: [filter, {$count: 'total'}],
            list: [
                filter,
                {$sort: {createTime: -1}},
                {$skip: (page - 1) * size},
                {$limit: size},
                {$project: {_id: 0, __v: 0}}
            ],
        }
    }]
    return new Promise((resolve, reject) => {
        model.aggregate(aggregate, (err, docs) => {
            if (!err) {
                resolve({
                    code: 1,
                    data: {
                        page, size,
                        total: docs[0].total[0] ? docs[0].total[0].total : 0,
                        list: docs[0].list
                    },
                    msg: '查询成功'
                });
            } else {
                reject({code: 0, data: null, msg: err.message});
            }
        })
    })
}

/**
 * 用户信息 查询
 * @param id                    用户ID 必填
 * @returns {Promise<object>}   结果
 */
const handleInfo = ({id}) => {
    return new Promise((resolve, reject) => {
        model.findOne({id}).exec((err, docs) => {
            if (docs) {
                resolve({code: 1, data: docs, msg: '查询成功'});
            } else {
                reject({code: 0, data: null, msg: '暂未查询到该用户'});
            }
        })
    })
}

module.exports = {model, handleLogin, handleRegister, handleAdd, handleDel, handleModify, handleList, handleInfo}
